#include "MainHeader.h"
long ho;
int DrawMapLoc(HDC hdc);
BOOL CALLBACK  MiniProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
RHeader* RoomHeader=GameEngine->Members.RoomHeader;
	u8 Width=0;
	u8 Height=0;
	
	switch (message) 
	{
	case WM_INITDIALOG:
		hwndMM = hWnd;
		
		break;
		
		
	case WM_LBUTTONDOWN:
		
		
		break;
	case WM_COMMAND:
		switch(LOWORD(wParam)){
			
		case cboMPal:
			Minimap.DrawTileset();
			break;
		case cboMAreaC:
			if(HIWORD(wParam) == CBN_SELCHANGE){
				Minimap.DecompressMap();
				Minimap.DrawMap();
				drawmm=0;
			}
			break;
		case cmdMMSave:
			if(drawmm)Minimap.SaveMap();
		if(GameEngine->isZM()){
			ho=((RoomOffsets[Combos[cArea].GetListIndex()]-0x8000000) + Combos[cRoom].GetListIndex()*0x3C);
		}else if (GameEngine->isMF()){
			ho=((RoomOffsets[Combos[cArea].GetListIndex()]-0x8000000) + Combos[cRoom].GetListIndex()*0x3C);
		}
		fseek(GBA.ROM,ho+0x35,SEEK_SET);
	    fwrite(&RoomHeader->bMiniMapRoomX,sizeof(u8),1,GBA.ROM);
		fwrite(&RoomHeader->bMiniMapRoomY,sizeof(u8),1,GBA.ROM);
	

			break;
		case WM_DESTROY:
			ShowWindow(hWnd,SW_HIDE);
			break;	
	
		}
		break;
	
		case WM_SHOWWINDOW:
			SendMessage(hwndMM,WM_COMMAND,LOWORD(cboMAreaC),0);
			break;
			
			
	}
	
	//	return DefWindowProc(hWnd, message, wParam, lParam);
	return 0;
}

int DrawMiniMap(){
	
	
	return 0;
}

mmD::mmD(){
	Zero();
}


mmD::~mmD(){
	Zero();
	Destroy();
}

int mmD::Zero()
{
	int a=0;
	int i =0;
	hwndMiniMap=NULL;
	hwndMiniTileset =NULL;
	memset(&MZMTilesetGraphics,0,0x3000);
	memset(&MZMPalette,0,sizeof(MZMPalette));
	for(i = 0; i<0x3000;i++)a+=MZMTilesetGraphics[i];
	for(i = 0; i<sizeof(MZMPalette);i++)a+=MZMPalette[i];
	return a;
}
int mmD::Clear(){
	memset(&MZMTilesetGraphics,0,0x3000);
	memset(&MZMPalette,0,sizeof(MZMPalette));
	return 0;
}
int mmD::Create(){
	RECT tr;
	int x=0;
	int y=0;
	int tc=0;
	int i=0;
	char buf[256];
		Vert.SetCnt(GetDlgItem(hwndMM,chkVert));
		Horz.SetCnt(GetDlgItem(hwndMM,chkHorz));
    switch(GameEngine->isZM()){
	case 0:
		if(GBA.ROM){
			//Need to read our arrays and translate shit in
			fseek(GBA.ROM,0x7601EC,SEEK_SET);
			fread(&MapList,4,0xB,GBA.ROM);
			fseek(GBA.ROM,0x40E0C4,SEEK_SET);
			fread(&MZMTilesetGraphics,1,0x3000,GBA.ROM);
			fseek(GBA.ROM,0x411360,SEEK_SET);       
			fread(&GBA.GBAPal,2,0xA0,GBA.ROM);
			GBA.DecodePal(GBA.GBAPal,MZMPalette,0xB, 0);
			ts.Load(MZMTilesetGraphics,384);
			
			//Should be all that is needed.
			Map.Create(2048,2048);
			
			MFMap.SetListIndex(0);
			GetWindowRect(GetDlgItem(hwndMM,framt),&tr);
			//Now would be the best time to create an HWND
			CreateMiniMapTileImage(tr.right - tr.left,tr.bottom-tr.top);
			GetWindowRect(GetDlgItem(hwndMM,fraMinimap),&tr);
			CreateMiniMapImage(tr.right - tr.left,tr.bottom-tr.top);
			Tileset.Create(tr.right-tr.left,tr.bottom - tr.top);
			Tileset.SetPalette(MZMPalette,0,0xa0);
			Map.SetPalette(MZMPalette,0,0xA0);
			cboPalette.Init(GetDlgItem(hwndMM,cboMPal));
			cboPalette.Clear();
			for(i=0;i<9;i++){
				sprintf(buf,"%X",i);
				cboPalette.Additem(buf);
			}
			cboPalette.SetListIndex(0);
			cboMArea.Init(GetDlgItem(hwndMM,cboMAreaC));
			cboMArea.Clear();
			cboMArea.Additem("Brinstar");
			cboMArea.Additem("Kraid");
			cboMArea.Additem("Norfair");
			cboMArea.Additem("Ridley");
			cboMArea.Additem("Tourian");
			cboMArea.Additem("Crateria");
			cboMArea.Additem("Chozodia");
			cboMArea.Additem("???");
			cboMArea.Additem("???");
			cboMArea.Additem("???");
			cboMArea.Additem("???");
			cboMArea.SetListIndex(Combos[cArea].GetListIndex());
			DrawTileset();
			
			
		}
		
		else
		{
			return 1;
		}
		
		break;
	case 1:
		if(GBA.ROM){
			//Need to read our arrays and translate shit in
			fseek(GBA.ROM,0x79BE5C,SEEK_SET);
			fread(&MapList,4,0xB,GBA.ROM);
			fseek(GBA.ROM,0x561fa8,SEEK_SET);
			fread(&MFTilesetGraphics,1,0x4000,GBA.ROM);
			fseek(GBA.ROM,0x5657AA,SEEK_SET);   
			GBA.GBAPal[0]=0;
			fread(&GBA.GBAPal[1],2,0xE0,GBA.ROM);
			GBA.DecodePal(GBA.GBAPal,MFPalette,0xB, 0);
			ts.Load(MFTilesetGraphics,430);
			
			//Should be all that is needed.
			Map.Create(2048,2048);
		
			GetWindowRect(GetDlgItem(hwndMM,framt),&tr);
			//Now would be the best time to create an HWND
			CreateMiniMapTileImage(tr.right - tr.left,tr.bottom-tr.top);
			GetWindowRect(GetDlgItem(hwndMM,fraMinimap),&tr);
			CreateMiniMapImage(tr.right - tr.left,tr.bottom-tr.top);
			Tileset.Create(tr.right-tr.left,tr.bottom - tr.top);
			Tileset.SetPalette(MFPalette,0,0xa0);
			Map.SetPalette(MFPalette,0,0xA0);
			cboPalette.Init(GetDlgItem(hwndMM,cboMPal));
			for(i=0;i<9;i++){
				sprintf(buf,"%X",i);
				cboPalette.Additem(buf);
			}
			cboPalette.SetListIndex(0);
			cboMArea.Init(GetDlgItem(hwndMM,cboMAreaC));
			cboMArea.Additem("Main Deck");
			cboMArea.Additem("SRX");
			cboMArea.Additem("TRO");
			cboMArea.Additem("PYR");
			cboMArea.Additem("AQA");
			cboMArea.Additem("NOC");
			cboMArea.Additem("Debug1");
			cboMArea.Additem("Debug2");
			cboMArea.Additem("Debug3");
		    cboMArea.Additem("Uknown");
			cboMArea.Additem("Uknown");
		

			cboMArea.SetListIndex(Combos[cArea].GetListIndex());
			DrawTileset();
			
			
		}
		
		else
		{
			return 1;
		}
		
		break;
	}
    
	
	return 0;
}

int mmD::CreateMiniMapTileImage(int Width,int Height){
	WNDCLASSEX blab5;
	memset(&blab5,0,sizeof(blab5));
	blab5.cbSize = sizeof(blab5);		   // size of structure 
	blab5.style = CS_HREDRAW | 
		CS_VREDRAW; 				   // redraw if size changes 
	blab5.lpfnWndProc = &MiniTilesetProc;	  // points to window procedure 
	blab5.cbClsExtra = NULL;				// no extra class memory 
	blab5.cbWndExtra =NULL; 			   // no extra window memory 
	blab5.hInstance = hGlobal;		   // handle to instance 
	blab5.hIcon = NULL; 			 // predefined app. icon 
	blab5.hCursor = NULL;				// predefined arrow 
	//blab5.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH);				   // white background brush 
	blab5.lpszMenuName =  NULL;    // name of menu resource 
	blab5.lpszClassName = "MapTiles";  // name of window class 
	
	
	// Register the window class. 
	RegisterClassEx(&blab5);
	
	hwndMiniTileset = CreateWindowEx(NULL,"MapTiles",NULL, WS_TABSTOP | WS_VISIBLE|WS_CHILD ,2,13,131,240,GetDlgItem(hwndMM,framt),0,hGlobal,0);
	
	
	ShowWindow(hwndMiniTileset,SW_SHOW);	
	return 0;
}

LRESULT CALLBACK MiniTilesetProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
	HDC hdc=NULL;
	PAINTSTRUCT ps;
	char txt[256]={0};
	switch (message) 
	{
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		Minimap.Tileset.Blit(hdc, 0,0,128 ,232,0,0);
		EndPaint(hWnd, &ps);
		break;
		
  		case WM_LBUTTONDOWN:
			Minimap.curtile= (Minimap.cboPalette.GetListIndex() * 0x1000) + (GetX(lParam)/8) + ((GetY(lParam)/8)*	16);
			
			break;
		case WM_RBUTTONDOWN:
            sprintf(txt,"Tile is: %X",(GetX(lParam)/8) + ((GetY(lParam)/8)*	16));
			MessageBox(0,txt,"Tile",MB_OK);

			break;
        case WM_COMMAND:
			switch(LOWORD(wParam)){
			case IDCANCEL:
				ShowWindow(hWnd,SW_HIDE);
				break;	
			}
			break;	
	}
	
    return DefWindowProc(hWnd, message, wParam, lParam);
	
}
int mmD::CreateMiniMapImage(int Width,int Height){
	WNDCLASSEX blab6;
	memset(&blab6,0,sizeof(blab6));
	blab6.cbSize = sizeof(blab6);		   // size of structure 
	blab6.style = CS_HREDRAW | 
		CS_VREDRAW; 				   // redraw if size changes 
	blab6.lpfnWndProc = &MiniGraphicProc;	  // points to window procedure 
	blab6.cbClsExtra = NULL;				// no extra class memory 
	blab6.cbWndExtra =NULL; 			   // no extra window memory 
	blab6.hInstance = hGlobal;		   // handle to instance 
	blab6.hIcon = NULL; 			 // predefined app. icon 
	blab6.hCursor = NULL;				// predefined arrow 
	//blab6.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH);				   // white background brush 
	blab6.lpszMenuName =  NULL;    // name of menu resource 
	blab6.lpszClassName = "MiniMap";  // name of window class 
	
	
	// Register the window class. 
	RegisterClassEx(&blab6);
	
	hwndMiniMap = CreateWindowEx(NULL,"MiniMap",NULL, WS_TABSTOP | WS_VISIBLE|WS_CHILD ,3,12,Width-3,Height-12,GetDlgItem(hwndMM,fraMinimap),0,hGlobal,0);
	
	
	ShowWindow(hwndMiniTileset,SW_SHOW);	
	return 0;
}
LRESULT CALLBACK MiniGraphicProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
	HDC hdc=NULL;
	PAINTSTRUCT ps;
	RHeader* RoomHeader=GameEngine->Members.RoomHeader;
	int srcx=0;
	int srcy=0;
	char txt[256]={0};
	switch (message) 
	{
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		if(GameEngine->isMF()){
			if(Minimap.MFMap.GetListIndex()==1){
				srcx = 15;
			    srcy=0;
			}else if(Minimap.MFMap.GetListIndex() == 2){
				srcy=15;
			    srcx=0;
            }else if(Minimap.MFMap.GetListIndex() == 3){
                srcy=15;
			    srcx=15;
			}
		}
		Minimap.Map.Blit(hdc, 0,0,256 ,256,0,0);
		DrawMapLoc(hdc);
		EndPaint(hWnd, &ps);
		break;
	case WM_LBUTTONDOWN:

		Minimap.RawMap[(GetX(lParam)/8) + ((GetY(lParam)/8)*32)] = Minimap.curtile+(Minimap.Vert.value() ? 0x800:0)+(Minimap.Horz.value() ? 0x400:0);
		Minimap.DrawMap();
		drawmm=1;
		break;
	case WM_RBUTTONDOWN:
 	    RoomHeader->bMiniMapRoomX=(GetX(lParam)/8);
		RoomHeader->bMiniMapRoomY=(GetY(lParam)/8);

	InvalidateRect(Minimap.hwndMiniMap,0,1);
		break;
		
		
		
	}
	
    return DefWindowProc(hWnd, message, wParam, lParam);
	
}
int mmD::DrawTileset(){
	int i =0;	
	int max=  ((GameEngine->isZM()) ? 512:384);
	Tileset.Clear();
	for(i= 0;i<max;i++){
		Tileset.Draw(ts,(i % 16)*8,(i/16)*8,(cboPalette.GetListIndex()*0x1000)+i);
	}
	InvalidateRect(hwndMiniTileset,0,1);
	return 0;
}

int mmD::DecompressMap(){
	u8 DecompBuf[32192]={0};
    memset(&GBA.CompBuffer,0,sizeof(GBA.CompBuffer));
	
	if(GBA.ROM){
        if(GameEngine->isZM()){
		 fseek(GBA.ROM,MapList[cboMArea.GetListIndex()]-0x8000000,SEEK_SET);
		}else if(GameEngine->isMF()){
		 fseek(GBA.ROM,MapList[cboMArea.GetListIndex()]-0x8000000,SEEK_SET);
		}
		fread(&GBA.CompBuffer,1,sizeof(GBA.CompBuffer),GBA.ROM);
		DSize=GBA.LZ77UnComp(GBA.CompBuffer, DecompBuf);
		//if(RawMap) delete[] RawMap;
		
		//RawMap=new unsigned short[DSize/2];
		RawMap.resize(DSize/2);
		//memcpy((u8*)RawMap[0],DecompBuf,DSize);
		u16* tmp=(u16*)DecompBuf;
		for(int i=0;i<RawMap.size();i++) RawMap[i]=tmp[i];
	}
	
	return 0;
}
int mmD::DrawMap(){
	u16 i =0;
	Map.Clear();
	for(i = 0; i<RawMap.size();i++){
		Map.Draw(ts,(i%32)*8,(i/32)*8,RawMap[i]);
	}
	InvalidateRect(hwndMiniMap,0,1);
	return 0;
}


int mmD::Destroy(){
   
	return 0;
}

int mmD::SaveMap(){
    u8 DecompBuf[32192]={0};

    u32 size=0;
	u32 tsize=0;
	u32 offset=0;
	u32 moffset=0;

	if(GameEngine->isZM()) moffset=0x7601EC;
	if(GameEngine->isMF()) moffset=0x79BE5C;
	if(GBA.ROM){
		
		size = GBA.LZ77Comp(DSize, (u8*)RawMap.front(), DecompBuf);
		//Test size
	    offset=GBA.FindFreeSpace(size+30, 0xFF);
		MapList[cboMArea.GetListIndex()]=offset+0x8000000;
		fseek(GBA.ROM,moffset,SEEK_SET);
		fwrite(MapList,4,0xB,GBA.ROM);
        fseek(GBA.ROM, MapList[cboMArea.GetListIndex()]-0x8000000,SEEK_SET);
		fwrite(DecompBuf,1,size,GBA.ROM);
	
		
	}
	
	return 0;
}
int DrawMapLoc(HDC hdc){
	RHeader* RoomHeader=GameEngine->Members.RoomHeader;
   RECT blah;
   int thisX=0;
   int thisY=0;
   int x=0;
   int y=0;
   int ThisArea=Combos[cArea].GetListIndex();
   int ThisMArea=Minimap.cboMArea.GetListIndex();
   int ThisRoom=Combos[cRoom].GetListIndex();
                //Check to see if the areas are the same 
	                   //If they aren't do draw
   int RegDraw  =(ThisArea == ThisMArea ? 1:0);
   int DebugDraw=(ThisArea==6 && ThisMArea>=7  && ThisRoom > 0x61 ? 1:0);
   if(RegDraw||DebugDraw){
	 HBRUSH curbrush = CreateSolidBrush(RGB(255, 0, 255));
     blah.left   =RoomHeader->bMiniMapRoomX*8;
     blah.right  =blah.left +((ThisLevelData->X+1)/16)*8;
	 blah.top    =RoomHeader->bMiniMapRoomY*8;
	 blah.bottom =blah.top+((ThisLevelData->Y)/10)*8;
     FrameRect(hdc, &blah,curbrush);
	 DeleteObject(curbrush);
   }
	return 0;
}





